package fun.werfamily.wf.base.aspect;

import fun.werfamily.wf.base.annotation.MustLogin;
import fun.werfamily.wf.base.dto.BaseUserInfoDTO;
import fun.werfamily.wf.base.exception.BaseCoreException;
import fun.werfamily.wf.base.util.TokenUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @Author: Mr.WenMing Zhang
 * @Date: 2022/07/29 17:41
 * @Description:
 **/
@Aspect
@Slf4j
@Component
public class AuthAspect {

    /**
     * 指定切入点
     */
    //@Pointcut("execution(public * fun.werfamily..*.*(..))")
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RestController)")
    public void cutMethod() {
    }

    /**
     * 前置通知：在目标方法执行前调用
     */
    @Before("cutMethod()")
    public void before(JoinPoint joinPoint) throws IOException {


    }

    /**
     * 环绕通知：在目标方法执行前后 增强
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("cutMethod()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("-----进入权限限制切面-----");
        ServletRequestAttributes servletContainer = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Long userId = null;
        if (null != servletContainer) {
            // 退出切面
            log.info("-----servletContainer为空，退出切面-----");
            HttpServletRequest request = servletContainer.getRequest();
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            Method method = signature.getMethod();
            MustLogin mustLogin = method.getAnnotation(MustLogin.class);
            log.info("mustLogin{}", mustLogin);
            if (null != mustLogin && !mustLogin.value()) {
                log.info("-----非强制登陆，接口放行{}-----", mustLogin.value());
            }else {
                try {
                    // 获取请求用户id
                    BaseUserInfoDTO baseUserInfoDTO = TokenUtil.parseToken(request);
                    log.info("tokenInfoDTO{}", baseUserInfoDTO);
                } catch (BaseCoreException baseCoreException) {
                    log.warn("-----得到token中的用户id， 异常-----");
                    throw baseCoreException;
                }
            }
        }
        proceedingJoinPoint.proceed();
    }

    /**
     * 后置通知：在目标方法执行后调用，若目标方法出现异常，则不执行
     */
    @AfterReturning("cutMethod()")
    public void afterReturning() {
    }

    /**
     * 后置/最终通知：无论目标方法在执行过程中出现一场都会在它之后调用
     */
    @After("cutMethod()")
    public void after() {
    }

    /**
     * 异常通知：目标方法抛出异常时执行
     */
    @AfterThrowing("cutMethod()")
    public void afterThrowing() {
    }
}
